/*
 * Copyright 2007 National Bioinformatics Network
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dgbgui.gui;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import ouroborus.TableSorter;
import dgbgui.DGBGUI;
import dgbgui.modeldocument.ModelDocument;
import dgbgui.modeldocument.ModelDrivenWorkspace;
import dgbgui.modeldocument.Query;
import dgbgui.modeldocument.QueryResult;
import dgbgui.modeldocument.ResultStore;
import dgbgui.modeldocument.primitives.Attribute;
import dgbgui.modeldocument.primitives.AttributeType;
import dgbgui.modeldocument.primitives.Conceptron;
import dgbgui.modeldocument.primitives.ConceptronType;
import dgbgui.modeldocument.primitives.Primitive;

public class ModelDrivenResultsInspector implements Observer {
    
    public ModelDrivenResultsInspector() {
        m_panel.removeAll();
        m_panel.add(new JLabel("No results."));
    }
    
    public void update(Observable source, Object data) {
        

        if ( source instanceof ResultStore ) {
            ResultStore.ObservableData observedData = (ResultStore.ObservableData)data;
            switch( observedData.getType() ) {
            case QUERY_SUBMITTED:
                m_panel.removeAll();
                m_panel.add(new JLabel("In progress..."));
                break;
            case RESULT_RECEIVED:
                // ----- Show the results -----
                
                m_panel.removeAll();

                // Get the target query
                Query targetQuery = ModelDrivenWorkspace.getInstance().getTargetQuery();
                // Can't assert here, as target might be unset on receiving a result
                // because it happens asynchronously
                if ( targetQuery != null ) {
                    // It's possible that the query is only received after the target
                    // query has been chnaged already, so check that the strings match
                    if ( ModelDrivenWorkspace.getInstance().getTargetQuery().getDefinition().getdgbQLString().equals(observedData.getQueryString()) ) {
                        QueryResult results = observedData.getQueryResult();

                        ConceptronType type = null;
                        
                        
                        Set<Conceptron> instances = new HashSet<Conceptron>();
                        for ( Primitive primitive : results.getPrimitives() ) {

                            // We only deal with instance results in the results inspector 
                            if ( primitive instanceof Conceptron ) {
                                Conceptron instance = (Conceptron)primitive;
                                // If it's the first one, store the type
                                if ( type == null ) {
                                    type = ModelDocument.getInstance().getConceptronType(instance);
                                } else {
                                    // All the conceptrons must be of the same type
                                    assert(ModelDocument.getInstance().getConceptronType(instance) == type);
                                }
                                
                                // Save the instance
                                instances.add(instance);
                            }
                        }
                        
                        if ( instances.size() > 0 ) {
                            
                            Object[] columnNames = null;
                            Object[][]rowData = null;

                            // The column names
                            columnNames = new String[type.m_attributeTypes.length];
                            Map<Long,Integer> typePositionMap = new HashMap<Long,Integer>();
                            int columnIndex = 0;
                            for ( AttributeType attrType : type.m_attributeTypes ) {
                                columnNames[columnIndex] = attrType.m_name;
                                typePositionMap.put(attrType.m_id,columnIndex);
                                ++columnIndex;
                            }
                            
                            // The rows
                            int row = 0;
                            rowData = new String[instances.size()][type.m_attributeTypes.length];
                            
                            // Populate
                            for ( Conceptron instance : instances ) {
                                for ( Attribute attr : instance.m_attributes ) {
                                    // Use the map of type IDs to column position now
                                    rowData[row][typePositionMap.get(attr.m_id)] = attr.m_value.toString();
                                }
                                ++row;
                            }
                            
                            DefaultTableModel tableModel = new DefaultTableModel(rowData,columnNames);
                            TableSorter sorter = new TableSorter(tableModel);
                            m_panel.setLayout(new BoxLayout(m_panel,BoxLayout.Y_AXIS));
                            JTable table = new JTable(sorter);
                            sorter.setTableHeader(table.getTableHeader());
                            m_panel.add(table.getTableHeader());
                            m_panel.add(table);
                            // Pack so the gui is updated. Will also expand if lots of results
                            DGBGUI.getInstance().getMainFrame().pack();
                        }
                    } 
                }  
                break;
                
            }

        }
    }
    
    public JComponent getComponent() {
        return m_panel;
    }

    JPanel m_panel = new JPanel();
    
}
